﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

using NIF.MobileActors.Core;

namespace NIF.MobileActors.Hosts
{
    public class ActorManager
    {
        public IActor CreateLocalActor(Type aType)
        {
            IActor actor = Activator.CreateInstance(aType, true) as IActor;
            System.Diagnostics.Debug.Assert(actor != null);

            this.Add(actor.ID, actor);

            Stream xAsm = File.OpenRead(aType.Assembly.Location);
            byte[] xBytes = new byte[xAsm.Length];
            xAsm.Read(xBytes, 0, xBytes.Length);
            AssemblyManager.Instance.Add(aType.Assembly.GetName().FullName, xBytes);
            return actor;
        }

        public IActor GetActor(ActorID id)
        {
            if (actors.Keys.Contains(id))
            {
                return actors[id];
            }
            else
            {
                return null;
            }
        }

        public ActorBase<T>[] GetActors<T>()
        {
            List<ActorBase<T>> ls = new List<ActorBase<T>>();
            foreach (IActor actor in actors.Values)
                if (actor is ActorBase<T>)
                    ls.Add(actor as ActorBase<T>);
            return ls.ToArray();
        }

        public bool IsLocalAssembly(ActorID id)
        {
            return actors.ContainsKey(id);
        }

        public void Add(ActorID id, IActor actor)
        {
            actors.AddOrUpdate(id, actor, (k, v) => v);
        }



        private ConcurrentDictionary<ActorID, IActor> actors
            = new ConcurrentDictionary<ActorID, IActor>();

        public static ActorManager Instance
        {
            get
            {
                if (m_instance == null)
                {
                    m_instance = new ActorManager();
                }
                return m_instance;
            }
        }
        private static ActorManager m_instance = null;
    }
}
